/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jamlu.framework.network.converter;

import android.support.annotation.NonNull;
import android.util.Log;

import com.blankj.utilcode.util.SPUtils;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.SerializedName;
import com.jamlu.framework.network.ConstantToken;

import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import retrofit2.Converter;

/**
 * 来自请求体：GsonRequestBodyConverter（修改convert方法）
 * Created by DMing on 2017/12/26.
 */
public final class FormGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8");
    @SuppressWarnings("unused")
    public FormGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    }

    @Override public RequestBody convert(@NonNull T value) throws IOException {
      String body = getFormProperty(value);
      return RequestBody.create(MEDIA_TYPE, body.getBytes());
    }

    public static Field[] getAllFields(Object object){
        Class clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    @SuppressWarnings("all")
    public String getFormProperty(Object bean){
        StringBuilder strBuilder = new StringBuilder();
//        Field[] fields = bean.getClass().getFields(); // 获取实体类的所有属性（不包括父类），返回Field数组
        Field[] fields = getAllFields(bean); // 获取实体类的所有属性(包括父类)，返回Field数组
        try {
            boolean first = false;
            for (Field field : fields) { // 遍历所有属性
                String name = field.getName(); // 获取属性的名字
                field.setAccessible(true); //设置些属性是可以访问的
                Object value = field.get(bean);//得到此属性的值
                Type type = field.getGenericType(); // 获取属性的类型
//                DLog.i("name: " + name + " value: " + value+" type: "+type+"  "+field.getModifiers());
                if (value == null && !name.equals("access_token")){ //排除null值的
                    continue;
                }
                if ((field.getModifiers() & (Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT)) != 0) { //排除静态 final 不能序列化
                    continue;
                }
                if (field.isSynthetic()) { //排除java自己添加的类
                    continue;
                }
                if (field.getType().isMemberClass()) { //排除内部类
                    continue;
                }
                SerializedName annotation = field.getAnnotation(SerializedName.class); //获取别名注解
                if (annotation != null) {
                    name = annotation.value();
                }
                if (!first){ //表单第一个是没有&的
                    first = true;
                }else {
                    strBuilder.append("&");
                }
                if (field.getType().isArray()) { //处理数组
                    strBuilder.append(name).append("=").append("[");
                    for(int i = 0; i< Array.getLength(value); i++){
                        if (i != 0 )strBuilder.append(",");
                        strBuilder.append(Array.get(value,i));
                    }
                    strBuilder.append("]");
                } else if (type == List.class || type == ArrayList.class || type == LinkedList.class){ //处理列表
                    List list = (List) value;
                    strBuilder.append(name).append("=").append("[");
                    for(int i = 0 ; i < list.size() ; i++) {
                        if (i != 0 )strBuilder.append(",");
                        strBuilder.append(list.get(i).toString());
                    }
                    strBuilder.append("]");
                } else{
                    if (name.equals("access_token")){ //更新token
                        strBuilder.append(name).append("=").append(SPUtils.getInstance(ConstantToken.TOKEN).getString(ConstantToken.ACCESS));
                    }else {
                        strBuilder.append(name).append("=").append(value);
                    }
                }
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return strBuilder.toString();
    }
}
